package cn.edu.cug.cs.gtl.docsrv.doc;

import cn.edu.cug.cs.gtl.common.Pair;
import cn.edu.cug.cs.gtl.mybatis.Session;
import cn.edu.cug.cs.gtl.mybatis.mapper.doc.*;
import cn.edu.cug.cs.gtl.mybatis.metadata.DocUtils;
import cn.edu.cug.cs.gtl.net.ftp.client.ClientFTP;
import cn.edu.cug.cs.gtl.protos.TimeValue;
import cn.edu.cug.cs.gtl.protoswrapper.TimeValueWrapper;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * 基于关系数据库Oracle+FTP实现的文档数据管理器
 * DOC_ITEM表中存放文档数据的条目信息
 * FTP Server中存放文档文件
 * 通过DOC_ITEM表中的DOC_URL指向服务器中的文件全名
 */
public class FTPDocManager extends DocManager {
    ClientFTP clientFTP;


    /**
     *
     * @param s
     * @param ftp
     */
    public FTPDocManager(Session s, ClientFTP ftp) {
        super(s);
        clientFTP=ftp;
    }


    private String getFtpRemoteDir(String docUrl){
        String[] ss = docUrl.split("/");
        //解析ftp地址  ftp://ip:port/remoteDir1/remoteDir2/fileName
        StringBuilder stringBuilder = new StringBuilder();
        if(ss.length <= 4) return "/";
        for (int i = 3; i < ss.length-1; i++) {
            stringBuilder.append("/");
            stringBuilder.append(ss[i]);

        }
        return stringBuilder.toString();
    }

    private String getFtpRemoteFilename(String docUrl){
        String[] ss = docUrl.split("/");
        return ss[ss.length-1];
    }

    /**
     *
     * @param docItem
     * @param docFile
     * @return
     */
    @Override
    public boolean insert(DocItem docItem, DocFile docFile){
        byte[] bytes = docFile.getDocRawBytes();
        //解析ftp地址  ftp://ip:port/remoteDir1/remoteDir2/fileName
        String docUrl = docItem.getDocUrl();
        String remoteDir = getFtpRemoteDir(docUrl);
        String remoteFileName = getFtpRemoteFilename(docUrl);
        //上传到ftp
        try{
            clientFTP.uploadBytes(bytes,remoteDir,remoteFileName);
        }catch (IOException e){
            e.printStackTrace();
        }
        DocItemMapper docItemMapper = session.getMapper(DocItemMapper.class);
        if(docItem.getDocInternalId()==null){
            docItem.setDocInternalId(docItemMapper.nextDocInternalId());
        }
        //上传到数据库
        docItemMapper.insert(docItem);
        session.commit();
        return true;
    }

    /**
     *
     * @param docAll
     * @return
     */
    @Override
    public  boolean insert(DocAll docAll){
        Pair<DocItem,DocFile> pair = DocUtils.fromDocAll(docAll);
        return insert(pair.getFirst(),pair.getSecond());

    }


    /**
     *
     * @param docItem 必须填充docInternalId
     * @return
     */
    @Override
    public boolean delete(DocItem docItem) {
        //解析docUrl 在ftp上，应该是这种形式 "ftp://ip:port/remoteDir1/remoteDir2/fileName"
        String docUrl = docItem.getDocUrl();
        String remoteDir = getFtpRemoteDir(docUrl);
        String remoteFileName = getFtpRemoteFilename(docUrl);
        //delete the file on ftp
        try{
            clientFTP.deleteFile(remoteDir,remoteFileName);
        }catch (IOException e) {
            e.printStackTrace();
        }
        //delete the docItem
        DocItemMapper docItemMapper = session.getMapper(DocItemMapper.class);
        docItemMapper.deleteByPrimaryKey(docItem.getDocInternalId());
        session.commit();
        return true;
    }

    /**
     *
     * @param docAll 必须填充docInternalId
     * @return
     */
    @Override
    public boolean delete(DocAll docAll) {
        return delete(DocUtils.fromDocAll(docAll).getFirst());
    }

    /**
     *
     * @param docItem 该对象的docInternalId必须填充
     * @param docFile 更新文档文件的内容
     * @return
     */
    @Override
    public boolean update(DocItem docItem, DocFile docFile) {
        //update docItem
        DocItemMapper docItemMapper = session.getMapper(DocItemMapper.class);
        docItemMapper.updateByPrimaryKey(docItem);

        //update the file
        // file on ftp is not allowed to update

        session.commit();
        return true;
    }

    @Override
    public boolean update(DocAll docAll) {
        return update(DocUtils.fromDocAll(docAll).getFirst(),DocUtils.fromDocAll(docAll).getSecond());
    }

    /**
     *
     * @param docInternalId
     * @return
     */
    @Override
    public DocAll queryByInternalId(BigDecimal docInternalId) {
        //从数据库中提取条目信息
        DocItemMapper docItemMapper = session.getMapper(DocItemMapper.class);
        DocItem docItem =  docItemMapper.selectByPrimaryKey(docInternalId);
        //ftp url:     ftp://124.71.9.22:21/remote/aaaa/Dir/remoteFileName
        String docUrl = docItem.getDocUrl();

        String remoteDir = getFtpRemoteDir(docUrl);
        String remoteFileName = getFtpRemoteFilename(docUrl);

        byte[] bytes = null;
        try{
            bytes = clientFTP.downloadBytes(remoteDir,remoteFileName);
        }catch (IOException e){
            e.printStackTrace();
        }
        DocFile docFile = new DocFile();
        docFile.setDocInternalId(docItem.getDocInternalId());
        docFile.setDocRawBytes(bytes);
        DocAll docAll = DocUtils.toDocAll(docItem,docFile);
        session.commit();
        return docAll;
    }

    @Override
    public List<DocAll> queryByTitle(String docEnTitle) {
        List<DocAll> res = new ArrayList<>();
        //从数据库中提取条目信息
        DocItemMapper docItemMapper = session.getMapper(DocItemMapper.class);
        List<DocItem> docItems = docItemMapper.selectByEnTitle(docEnTitle);

        for (DocItem docItem : docItems) {
            //解析ftp地址
            String docUrl = docItem.getDocUrl();
            String remoteDir = getFtpRemoteDir(docUrl);
            String remoteFileName = getFtpRemoteFilename(docUrl);
            byte[] bytes = null;
            try {
                bytes = clientFTP.downloadBytes(remoteDir, remoteFileName);
            } catch (IOException e) {
                e.printStackTrace();
            }
            DocFile docFile = new DocFile();
            docFile.setDocInternalId(docItem.getDocInternalId());
            docFile.setDocRawBytes(bytes);
            DocAll docAll = DocUtils.toDocAll(docItem,docFile);
            res.add(docAll);
        }
        session.commit();
        return res;
    }

    @Override
    public List<DocAll> queryByComment(String docCnTitle) {
        List<DocAll> res = new ArrayList<>();
        //从数据中提取条目信息
        DocItemMapper docItemMapper = session.getMapper(DocItemMapper.class);
        List<DocItem> docItems = docItemMapper.selectByCnTitle(docCnTitle);
        for (DocItem docItem : docItems){
            //解析ftp地址
            String docUrl = docItem.getDocUrl();
            String remoteDir = getFtpRemoteDir(docUrl);
            String remoteFileName = getFtpRemoteFilename(docUrl);
            byte[] bytes = null;
            try{
                bytes = clientFTP.downloadBytes(remoteDir,remoteFileName);
            }catch (IOException e){
                e.printStackTrace();
            }

            DocFile docFile = new DocFile();
            docFile.setDocInternalId(docItem.getDocInternalId());
            docFile.setDocRawBytes(bytes);
            DocAll docAll = DocUtils.toDocAll(docItem,docFile);
            res.add(docAll);
        }
        session.commit();
        return res;
    }

    @Override
    public List<DocAll> queryByType(String docType) {
        List<DocAll> res = new ArrayList<>();
        DocItemMapper docItemMapper = session.getMapper(DocItemMapper.class);
        List<DocItem> docItems = docItemMapper.selectByType(docType);
        for (DocItem docItem : docItems){
            String docUrl = docItem.getDocUrl();
            String remoteDir = getFtpRemoteDir(docUrl);
            String remoteFileName = getFtpRemoteFilename(docUrl);
            byte[] bytes = null;
            try{
                bytes = clientFTP.downloadBytes(remoteDir,remoteFileName);
            }catch (IOException e){
                e.printStackTrace();
            }
            DocFile docFile = new DocFile();
            docFile.setDocInternalId(docItem.getDocInternalId());
            docFile.setDocRawBytes(bytes);
            DocAll docAll = DocUtils.toDocAll(docItem,docFile);
            res.add(docAll);
        }
        session.commit();
        return res;

    }

    @Override
    public List<DocAll> queryByAppendDate(TimeValue begin, TimeValue end) {
        List<DocAll> res = new ArrayList<>();
        DocItemMapper docItemMapper = session.getMapper(DocItemMapper.class);
        List<DocItem> docItems = docItemMapper.selectByAppendDate(TimeValueWrapper.toUtilDate(begin),TimeValueWrapper.toUtilDate(end));
        for (DocItem docItem : docItems){
            String docUrl = docItem.getDocUrl();
            String remoteDir = getFtpRemoteDir(docUrl);
            String remoteFileName = getFtpRemoteFilename(docUrl);

            byte[] bytes = null;
            try{
                bytes = clientFTP.downloadBytes(remoteDir,remoteFileName);
            }catch (IOException e){
                e.printStackTrace();
            }
            DocFile docFile = new DocFile();
            docFile.setDocInternalId(docItem.getDocInternalId());
            docFile.setDocRawBytes(bytes);
            DocAll docAll = DocUtils.toDocAll(docItem,docFile);
            res.add(docAll);
        }
        session.commit();
        return res;
    }


    /**
     * 根据文件名插入文档数据基本用不到
     * @param docItem 该文档的元数据
     * @param localSingleFile 文档文件全名
     * @return
     */
    @Override
    public boolean insert(DocItem docItem, String localSingleFile) {
        try{
            String docUrl = docItem.getDocUrl();
            String remoteDir = getFtpRemoteDir(docUrl);
            clientFTP.uploadFile(remoteDir,new File(localSingleFile));
        }catch (IOException e){
            e.printStackTrace();
        }
        DocItemMapper docItemMapper = session.getMapper(DocItemMapper.class);
        if(docItem.getDocInternalId()==null) {
            docItem.setDocInternalId(docItemMapper.nextDocInternalId());
        }
        docItemMapper.insert(docItem);
        session.commit();
        return true;
    }

    @Override
    public boolean insert(String localDir) {
        try{
            clientFTP.uploadFolder(localDir);
        }catch (IOException e ){
            e.printStackTrace();
        }
        File file = new File(localDir);
        if(file.isDirectory()){
            File[] files = file.listFiles();
            for (File f : files){
                DocItemMapper docItemMapper = session.getMapper(DocItemMapper.class);
                DocItem docItem = new DocItem();
                docItem.setDocAppendDate(new Date());
                String[] ss = localDir.split("/");
                docItem.setDocUrl("ftp://124.71.9.22:21/"+ ss[ss.length-1]+"/"+f.getName());
                docItem.setDocEnTitle(f.getName());
                docItem.setDocInternalId(docItemMapper.nextDocInternalId());
                docItemMapper.insert(docItem);
            }
        }
        session.commit();
        return true;
    }





}
